<template>
  <div>
    <div>
      <!-- 查询部分 -->
      <div class="mg-0_5em">
        <el-form :inline="true" ref="tagQueryRef" class="demo-form-inline">
          <el-form-item label="标签名" prop="tagName">
            <el-input v-model="tagName" placeholder="标签名" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" :icon="Search" @click="initTagList">查询</el-button>
            <el-button type="success" :icon="Refresh" @click="resetQuery">重置</el-button>
            <el-button type="primary" :icon="CirclePlus" @click="switchDialog">新增标签</el-button>
          </el-form-item>
        </el-form>
      </div>

      <!--   词云部分  -->
      <div>
        <div class="word-cloud-container">
          <svg style="background-color: white; border-radius: 50%" :width="width" :height="height" ref="test" @mousemove="listener($event)">
            <a
              class="word-cloud-font"
              :href="tag.href"
              v-for="(tag, index) in tags"
              :key="tag.id"
              @mouseenter="mouseenter($event)"
              @mouseleave="mouseleave($event)">
              <text :x="tag.x" :y="tag.y" :fill="colors[index]" :font-size="tag.size" :fill-opacity="(400 + tag.z) / 600">
                {{ tag.label }}
              </text>
            </a>
          </svg>
        </div>
      </div>
    </div>
    <!-- 新增弹框 -->
    <div>
      <el-dialog v-model="showDialog" title="新增标签" width="30%" center>
        <el-form :model="tagDTO" ref="tagDTORef" :label-width="100" label-position="left">
          <el-form-item label="标签名称" prop="tagName" :rules="required">
            <el-input v-model="tagDTO.tagName" placeholder="标签名称"></el-input>
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="switchDialog()"> 取 消 </el-button>
            <el-button type="primary" @click="add">提 交</el-button>
          </span>
        </template>
      </el-dialog>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed } from 'vue'
import { CirclePlus, Refresh, Search } from '@element-plus/icons-vue'
import Tag from '@/api/blog/tag'
import { required } from '@/utils/FormRule'

// 生命周期, 初始化数据
onMounted(async () => {
  await initTagList()
  initWordCloud()
})

// 查询条件
const tagName = ref('')

// 分类数据
const tagList = ref([])

/**
 * 初始化列表
 */
async function initTagList() {
  const { result } = await Tag.list({ tagName: tagName.value, all: true })
  tagList.value = []
  result.forEach((tag) => {
    tagList.value.push({
      label: tag,
      value: tag,
    })
  })
}

// 查询条件表单
const tagQueryRef = ref()

// 重置查询条件
function resetQuery() {
  tagName.value = ''
  initTagList()
}

// 弹框开关
const showDialog = ref(false)

// 分类参数
const tagDTO = ref({
  tagName: '',
})
// 新增表单Form
const tagDTORef = ref()

// 弹框开关
function switchDialog() {
  tagDTORef.value !== undefined && tagDTORef.value.resetFields()
  showDialog.value = !showDialog.value
}

const emits = defineEmits(['success'])

// 新增一个分类
function add() {
  tagDTORef.value.validate(async (valid) => {
    if (valid) {
      await Tag.create(tagDTO.value.tagName)
      switchDialog()
      await initTagList()
      initWordCloud()
    }
  })
}

//  以下是词云图部分

const tags = ref([])
const tagsNum = ref(0)
const maxSize = ref(44)
const minSize = ref(14)
const speedX = ref(Math.PI / 360 / 1.5)
const speedY = ref(Math.PI / 360 / 1.5)
const RADIUS = ref(250)
const width = ref(700)
const height = ref(500)
const CX = computed(() => width.value / 2)
const CY = computed(() => height.value / 2)
const timer = ref(null)
const colors = ref([])

function initWordCloud() {
  //初始化标签位置
  changeColors()
  tags.value = []
  tagsNum.value = tagList.value.length
  for (let i = 0; i < tagList.value.length; i++) {
    let tag = {}
    let k = -1 + (2 * (i + 1) - 1) / tagsNum.value
    let a = Math.acos(k)
    let b = a * Math.sqrt(tagsNum.value * Math.PI) //计算标签相对于球心的角度

    tag.label = tagList.value[i].label
    tag.value = tagList.value[i].value
    let size = minSize.value + parseInt((tagList.value[i].weight / 100) * 20)
    tag.size = size > maxSize.value ? maxSize.value : size
    // tag.href = "";

    tag.x = CX.value + RADIUS.value * Math.sin(a) * Math.cos(b) //根据标签角度求出标签的x,y,z坐标
    tag.y = CY.value + RADIUS.value * Math.sin(a) * Math.sin(b)
    tag.z = RADIUS.value * Math.cos(a)
    tags.value.push(tag)
  }
}

// 纵向
function rotateX(angleX) {
  let cos = Math.cos(angleX)
  let sin = Math.sin(angleX)
  for (let tag of tags.value) {
    let y1 = (tag.y - CY.value) * cos - tag.z * sin + CY.value
    let z1 = tag.z * cos + (tag.y - CY.value) * sin
    tag.y = y1
    tag.z = z1
  }
}

// 横向
function rotateY(angleY) {
  let cos = Math.cos(angleY)
  let sin = Math.sin(angleY)
  for (let tag of tags.value) {
    let x1 = (tag.x - CX.value) * cos - tag.z * sin + CX.value
    let z1 = tag.z * cos + (tag.x - CX.value) * sin
    tag.x = x1
    tag.z = z1
  }
}

// 监听鼠标方向
function listener(e) {
  let x = e.clientX - CX.value
  let y = e.clientY - CY.value
  if (x * 0.0001 > 0 && y * 0.0001 > 0) {
    speedX.value = -Math.min(RADIUS.value * 0.00002, x * 0.0002)
    speedY.value = -Math.min(RADIUS.value * 0.00002, y * 0.0002)
  } else if (x * 0.0001 < 0 && y * 0.0001 < 0) {
    speedX.value = -Math.max(-RADIUS.value * 0.00002, x * 0.0002)
    speedY.value = -Math.max(-RADIUS.value * 0.00002, y * 0.0002)
  } else {
    speedX.value = x * 0.0001 > 0 ? Math.min(RADIUS.value * 0.00002, x * 0.0001) : Math.max(-RADIUS.value * 0.00002, x * 0.0001)
    speedY.value = y * 0.0001 > 0 ? Math.min(RADIUS.value * 0.00002, y * 0.0001) : Math.max(-RADIUS.value * 0.00002, y * 0.0001)
  }
}

// 鼠标进入文字
function mouseenter(e) {
  // 修改透明度
  let doms = document.getElementsByClassName('fontA')
  for (let i = 0; i < doms.length; i++) {
    doms[i].childNodes[0].style.fillOpacity = '0.3'
  }
  e.target.childNodes[0].style.fillOpacity = 1

  // 停止动画
  clearInterval(timer.value)
  timer.value = null
}

// 鼠标离开文字
function mouseleave() {
  // 修改透明度
  let doms = document.getElementsByClassName('word-cloud-font')
  for (let i = 0; i < doms.length; i++) {
    doms[i].childNodes[0].style.fillOpacity = ''
  }

  // 开始动画
  if (timer.value) {
    clearInterval(timer.value)
    timer.value = null
  }
  timer.value = setInterval(() => {
    rotateX(speedX.value)
    rotateY(speedY.value)
  }, 17)
}

// 颜色
function changeColors() {
  //随机变色
  for (let i = 0; i < 22; i++) {
    let r = Math.floor(Math.random() * 256)
    let g = Math.floor(Math.random() * 256)
    let b = Math.floor(Math.random() * 256)
    colors.value[i] = 'rgb(' + r + ',' + g + ',' + b + ')'
  }
}
</script>

<style scoped lang="scss">
.word-cloud-container {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
}
.word-cloud-font {
  font-weight: bold;
  font-family: Apple LiGothic Medium;
}
</style>
